package com.chuangke.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chuangke.admin.dao.mapper.SysUserDataDeptMapper;
import com.chuangke.admin.dao.mapper.SysUserMapper;
import com.chuangke.admin.dto.UserDeptRequest;
import com.chuangke.admin.entity.SysDept;
import com.chuangke.admin.entity.SysUser;
import com.chuangke.admin.entity.SysUserDataDept;
import com.chuangke.admin.service.SysDeptService;
import com.chuangke.admin.service.SysUserDataDeptService;
import com.chuangke.common.constant.CacheKeyConstants;
import com.chuangke.common.event.file.FilePermissionChangeEvent;
import com.chuangke.common.idgen.IdManager;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SysUserDataDeptServiceImpl extends ServiceImpl<SysUserDataDeptMapper, SysUserDataDept> implements SysUserDataDeptService {

	public static final String INHERIT_ROLE = "0";
	
	@Autowired
	private SysDeptService sysDeptService;

	@Autowired
	private SysUserDataDeptMapper sysUserDataDeptMapper;
	
	@Autowired
	private ApplicationEventPublisher eventPublisher;
	
	@Autowired
	private SysUserMapper sysUserMapper;

	@CacheEvict(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void save(UserDeptRequest userDeptRequest) {
		sysUserDataDeptMapper.delete(new QueryWrapper<SysUserDataDept>().lambda().eq(SysUserDataDept::getUserId, userDeptRequest.getUserId()));
		for(SysUserDataDept sysUserDataDept:getSysUserDeptList(userDeptRequest)) {
			sysUserDataDeptMapper.insert(sysUserDataDept);
		}
		//更新角色
//		sysUserService.changeInheritRole(userDeptRequest.getUserId(),INHERIT_ROLE);
		sysUserMapper.update(null, new UpdateWrapper<SysUser>().lambda().set(SysUser::getIsInheritRole, INHERIT_ROLE).eq(SysUser::getId, userDeptRequest.getUserId()));
		eventPublisher.publishEvent(new FilePermissionChangeEvent(this));
	}

	@CacheEvict(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Override
	public void delete(String userId) {
		sysUserDataDeptMapper.delete(new QueryWrapper<SysUserDataDept>().lambda().eq(SysUserDataDept::getUserId, userId));
		eventPublisher.publishEvent(new FilePermissionChangeEvent(this));
	}
	
	@CacheEvict(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Override
	public void removeByIds(List<String> ids) {
		super.removeBatchByIds(ids) ;
		eventPublisher.publishEvent(new FilePermissionChangeEvent(this));
	}

	private List<SysUserDataDept> getSysUserDeptList(UserDeptRequest userDeptRequest) {
		List<SysUserDataDept> list = new ArrayList<>();
		for (String dept : userDeptRequest.getDeptList()) {
			SysUserDataDept sysUserDataDept = new SysUserDataDept();
			sysUserDataDept.setUserId(userDeptRequest.getUserId());
			sysUserDataDept.setDeptId(dept);
			sysUserDataDept.setId(IdManager.nextId());
			list.add(sysUserDataDept);
		}
		return list;
	}

	@Cacheable(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Override
	public Map<String, List<SysUserDataDept>> findAll() {
		Map<String, SysDept> map = sysDeptService.findMap();
		List<SysUserDataDept> list = sysUserDataDeptMapper.selectList(new QueryWrapper<>());
		list.forEach(sysUserDept -> {
			SysDept sysDept = map.get(sysUserDept.getDeptId().toString());
			if (sysDept != null) {
				sysUserDept.setDeptName(sysDept.getName());
			}
		});

		return list.stream().collect(Collectors.groupingBy(SysUserDataDept::getUserId));
	}

	@Override
	public List<SysUserDataDept> find(String userId) {
		Map<String, List<SysUserDataDept>> map = ((SysUserDataDeptService) AopContext.currentProxy()).findAll();
		return map== null ? new ArrayList<>() : map.get(userId)==null ? new ArrayList<>(): map.get(userId);
	}

	@Override
	public List<SysDept> findUserDeptWithChildren(String userId) {
		List<SysDept> sysDeptList = sysDeptService.findListWithChildren() ;
		Map<String, SysDept> sysDeptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getId, a -> a));
		Map<String, List<SysUserDataDept>> map = ((SysUserDataDeptService) AopContext.currentProxy()).findAll();
		List<SysUserDataDept> userDeptList = map== null ? new ArrayList<>() : map.get(userId); 
		userDeptList = userDeptList==null ? new ArrayList<>() : userDeptList;
		List<SysDept> userDeptListWithChildren = new ArrayList<>() ;
		
		for(SysUserDataDept userDept: userDeptList) {
			SysDept dept = sysDeptMap.get(userDept.getDeptId()) ;
			userDeptListWithChildren.add(dept);
			if(!CollectionUtils.isEmpty(dept.getChildren())) {
				v1(userDeptListWithChildren,dept.getChildren()) ;
			}
		}
		return userDeptListWithChildren;
	}
	
	private void v1(List<SysDept> userDeptListWithChildren,List<SysDept> deptList) {
		for(SysDept dept: deptList) {
			userDeptListWithChildren.add(dept) ;
			if(!CollectionUtils.isEmpty(dept.getChildren())) {
				v1(userDeptListWithChildren,dept.getChildren()) ;
			}
		}
	}
	
	@CacheEvict(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveBatchDataRule(List<SysUserDataDept> list) {
		this.saveBatch(list);
	}

	@CacheEvict(cacheNames = CacheKeyConstants.SYS_USER_DEPT, key = "'" + CacheKeyConstants.SYS_USER_DEPT + "'")
	@Override
	public void removeDataRule(LambdaQueryWrapper<SysUserDataDept> lambdaQueryWrapper) {
		this.remove(lambdaQueryWrapper);
	}

}
